/*
** Copyright (C) 2010 Calin Radoni
**
** This file is part of CHScanner.
**
** CHScanner is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** CHScanner is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with CHScanner. If not, see <http://www.gnu.org/licenses/>.
*/

// DlgScanCfg.cpp : implementation file

#include "stdafx.h"
#include "CHScanner.h"
#include "DlgScanCfg.h"
#include ".\dlgscancfg.h"

//---------------------------------------------------------------------------

IMPLEMENT_DYNAMIC(DlgScanCfg, CRgnDialog)
DlgScanCfg::DlgScanCfg(CWnd* pParent /*=NULL*/) : CRgnDialog(DlgScanCfg::IDD, pParent)
, vDesc(_T(""))
, vComm(_T(""))
, vAS(_T(""))
, vMssg(_T(""))
, vMssd(_T(""))
, vMssi(_T(""))
, vMwt(_T(""))
, vMdt(_T(""))
, vScanOrder(0)
, vMimic(0)
, vArpCache(0)
, vScanAll(FALSE)
, vShowArpDisc(FALSE)
{
	skinIn = NULL;
	retVal = false;

	iconUp = NULL;
	iconDown = NULL;
}

DlgScanCfg::~DlgScanCfg()
{
	if(iconUp!=NULL){
		DeleteObject(iconUp);
		iconUp = NULL;
	}
	if(iconDown!=NULL){
		DeleteObject(iconDown);
		iconDown = NULL;
	}
}

//---------------------------------------------------------------------------

void DlgScanCfg::DoDataExchange(CDataExchange* pDX)
{
	CRgnDialog::DoDataExchange(pDX);

	DDX_Control(pDX, IDC_STA_DESC,        staDesc);
	DDX_Control(pDX, IDC_STA_COMM,        staComm);
	DDX_Control(pDX, IDC_STA_ADDR,        staAS);
	DDX_Control(pDX, IDC_STA_MSSG,        staMSSG);
	DDX_Control(pDX, IDC_STA_MSSD,        staMSSD);
	DDX_Control(pDX, IDC_STA_MSSI,        staMSSI);
	DDX_Control(pDX, IDC_STA_MWT,         staMWT);
	DDX_Control(pDX, IDC_STA_MDT,         staMDT);
	DDX_Control(pDX, IDC_EDIT_DESC,       editDesc);
	DDX_Control(pDX, IDC_EDIT_COMM,       editComm);
	DDX_Control(pDX, IDC_EDIT_ADDR,       editAS);
	DDX_Control(pDX, IDC_EDIT_MSSG,       editMSSG);
	DDX_Control(pDX, IDC_EDIT_MSSD,       editMSSD);
	DDX_Control(pDX, IDC_EDIT_MSSI,       editMSSI);
	DDX_Control(pDX, IDC_EDIT_MWT,        editMWT);
	DDX_Control(pDX, IDC_EDIT_MDT,        editMDT);
	DDX_Control(pDX, IDC_LIST_SCANDET,    listDet);
	DDX_Control(pDX, IDC_CMB_SCANORDER,   cmbScanOrder);
	DDX_Control(pDX, IDC_CMB_MIMIC,       cmbMimic);
	DDX_Control(pDX, IDC_CMB_ARPC,        cmbArpCache);
	DDX_Control(pDX, IDC_CHK_SCANALL,     chkScanAll);
	DDX_Control(pDX, IDC_CHK_SHOWARPDISC, chkShowArpDisc);

	DDX_Control(pDX, IDC_BTN_OK,          btnOk);
	DDX_Control(pDX, IDC_BTN_CANCEL,      btnCancel);
	DDX_Control(pDX, IDC_BTN_ADD,         btnAdd);
	DDX_Control(pDX, IDC_BTN_EDIT,        btnEdit);
	DDX_Control(pDX, IDC_BTN_DEL,         btnDel);
	DDX_Control(pDX, IDC_BTN_UP,          btnUp);
	DDX_Control(pDX, IDC_BTN_DW,          btnDown);
	DDX_Control(pDX, IDC_BTN_ASH,         btnAsh);

	DDX_Text(pDX, IDC_EDIT_DESC,          vDesc);
	DDX_Text(pDX, IDC_EDIT_COMM,          vComm);
	DDX_Text(pDX, IDC_EDIT_ADDR,          vAS);
	DDX_Text(pDX, IDC_EDIT_MSSG,          vMssg);
	DDX_Text(pDX, IDC_EDIT_MSSD,          vMssd);
	DDX_Text(pDX, IDC_EDIT_MSSI,          vMssi);
	DDX_Text(pDX, IDC_EDIT_MWT,           vMwt);
	DDX_Text(pDX, IDC_EDIT_MDT,           vMdt);
	DDX_CBIndex(pDX, IDC_CMB_SCANORDER,   vScanOrder);
	DDX_CBIndex(pDX, IDC_CMB_MIMIC,       vMimic);
	DDX_CBIndex(pDX, IDC_CMB_ARPC,        vArpCache);
	DDX_Check(pDX, IDC_CHK_SCANALL,       vScanAll);
	DDX_Check(pDX, IDC_CHK_SHOWARPDISC,   vShowArpDisc);
}

//---------------------------------------------------------------------------

BEGIN_MESSAGE_MAP(DlgScanCfg, CRgnDialog)
	ON_BN_CLICKED(IDC_BTN_OK,     OnBnClickedBtnOk)
	ON_BN_CLICKED(IDC_BTN_CANCEL, OnBnClickedBtnCancel)
	ON_BN_CLICKED(IDC_BTN_ADD,    OnBnClickedBtnAdd)
	ON_BN_CLICKED(IDC_BTN_EDIT,   OnBnClickedBtnEdit)
	ON_BN_CLICKED(IDC_BTN_DEL,    OnBnClickedBtnDel)
	ON_BN_CLICKED(IDC_BTN_UP,     OnBnClickedBtnUp)
	ON_BN_CLICKED(IDC_BTN_DW,     OnBnClickedBtnDw)
	ON_BN_CLICKED(IDC_BTN_ASH,    OnBnClickedBtnAsh)
	ON_NOTIFY(NM_DBLCLK, IDC_LIST_SCANDET, OnNMDblclkListScandet)
END_MESSAGE_MAP()

//---------------------------------------------------------------------------

void DlgScanCfg::ResizeChilds(void)
{
	RECT rect;
	int xx, yy, ww, hh;	// client area dimensions
	int dd;				// inter-element space
	int lw;			    // width of label elements
	int ew, eh, ews;	// width and height of edit elements
	int dw, dh;			// width and height of listview element
	int bw, bh;			// width and height of button elements
	int cw, ch;			// width and height of combobox elements
	int kw, kh;			// width and height of checkbox elements
	int tw;				// total required width and height
	int mx, my;		    // left and top spaces

	int posx1, posx2, posx3;
	int posy, deltay;

	dd = 2;

	xx = clientRect.left;
	yy = clientRect.top;
	ww = clientRect.right - clientRect.left;
	hh = clientRect.bottom - clientRect.top;

	staDesc.GetWindowRect(&rect);
	lw = rect.right - rect.left;

	editDesc.GetWindowRect(&rect);
	ew = rect.right - rect.left;

	editMSSG.GetWindowRect(&rect);
	ews = rect.right - rect.left;

	listDet.GetWindowRect(&rect);
	dh = rect.bottom - rect.top;
	dw = rect.right - rect.left;

	btnOk.GetWindowRect(&rect);
	bh = rect.bottom - rect.top;
	bw = rect.right - rect.left;

	cmbScanOrder.GetWindowRect(&rect);
	ch = rect.bottom - rect.top;

	chkShowArpDisc.GetWindowRect(&rect);
	kh = rect.bottom - rect.top;

	eh = ch;

	tw = lw + ew + dd;

	mx = dd;
	my = dd;

	posx1  = xx + mx;
	posx2  = posx1 + lw + dd;
	posx3  = posx2 + ews + dd;

	posy   = yy + my;
	deltay = eh + dd;

	cw = ew - ews - dd;
	kw = cw - dd - bh - dd - bh;

	staDesc.MoveWindow (posx1, posy, lw, eh, TRUE);
	editDesc.MoveWindow(posx2, posy, ew, eh, TRUE);
	posy += deltay;
	staComm.MoveWindow (posx1, posy, lw, eh, TRUE);
	editComm.MoveWindow(posx2, posy, ew, eh, TRUE);
	posy += deltay;
	staAS.MoveWindow   (posx1, posy, lw, eh, TRUE);
	editAS.MoveWindow  (posx2, posy, ew - dd - bh, eh, TRUE);
	btnAsh.MoveWindow  (posx2 + ew - bh, posy, bh, eh, TRUE);
	posy += deltay;

	staMSSG.MoveWindow     (posx1, posy, lw,  eh, TRUE);
	editMSSG.MoveWindow    (posx2, posy, ews, eh, TRUE);
	cmbScanOrder.MoveWindow(posx3, posy, cw,  ch, TRUE);
	posy += deltay;
	staMSSD.MoveWindow     (posx1, posy, lw,  eh, TRUE);
	editMSSD.MoveWindow    (posx2, posy, ews, eh, TRUE);
	cmbMimic.MoveWindow    (posx3, posy, cw,  ch, TRUE);
	posy += deltay;
	staMSSI.MoveWindow     (posx1, posy, lw,  eh, TRUE);
	editMSSI.MoveWindow    (posx2, posy, ews, eh, TRUE);
	cmbArpCache.MoveWindow (posx3, posy, cw,  ch, TRUE);
	posy += deltay;

	staMWT.MoveWindow        (posx1, posy, lw,  eh, TRUE);
	editMWT.MoveWindow       (posx2, posy, ews, eh, TRUE);
	chkShowArpDisc.MoveWindow(posx3, posy + dd, kw,  kh, TRUE);
	posy += deltay;

	staMDT.MoveWindow        (posx1, posy, lw,  eh, TRUE);
	editMDT.MoveWindow       (posx2, posy, ews, eh, TRUE);
	chkScanAll.MoveWindow    (posx3, posy + dd, kw,  kh, TRUE);
	posy += deltay;

	posx2 = posx1 + tw - bh;
	posx3 = posx2 - dd - bh;
	btnDown.MoveWindow(posx2, posy - bh - dd, bh, bh, TRUE);
	btnUp.MoveWindow  (posx3, posy - bh - dd, bh, bh, TRUE);

	listDet.MoveWindow(posx1, posy, tw, dh, TRUE);
	posy += dd + dh;

	btnAdd.MoveWindow(posx1, posy, bw, bh, TRUE);
	posx1 += dd + bw;
	btnEdit.MoveWindow(posx1, posy, bw, bh, TRUE);
	posx1 += dd + bw;
	btnDel.MoveWindow(posx1, posy, bw, bh, TRUE);

	posx1 = xx + mx + tw - bw;
	btnCancel.MoveWindow(posx1, posy, bw, bh, TRUE);
	posx1 -= (dd + bw);
	btnOk.MoveWindow(posx1, posy, bw, bh, TRUE);
}

bool DlgScanCfg::GetMinimumSize(RECT* rectIn)
{
	if(rectIn==NULL) return false;

	rectIn->left   = 0;
	rectIn->right  = 483;
	rectIn->top    = 0;
	rectIn->bottom = 340;

	return true;
}

//---------------------------------------------------------------------------

void DlgScanCfg::BuildPosValues(void)
{
	WorkCfgElement* elem;
	int i, cnt, pos;

	wc.SortTheListOfJobs();

	pos = 0;
	cnt = wc.GetJobCount();

	for(i=0; i<cnt; i++){
		elem = wc.GetJobElement(i);
		if(elem!=NULL){
			elem->pos = pos;
			pos++;
		}
	}
}

void DlgScanCfg::RefreshList(void)
{
	WorkCfgElement* elem;
	int i, cnt;

	listDet.DeleteAllItems();

	BuildPosValues();
	//wc.SortTheListOfJobs();

	cnt = wc.GetJobCount();

	for(i=0; i<cnt; i++){
		elem = wc.GetJobElement(i);
		if(elem!=NULL)
			AddListElement(elem);
	}
}

//---------------------------------------------------------------------------

bool DlgScanCfg::SetItemProperties(int itemIdx, WorkCfgElement* elemIn)
{
	CString str;

	if(!listDet.SetItemData(itemIdx, (DWORD_PTR)elemIn))
		return false;

	str = wd.GetPhaseName(elemIn->phaseType);
	if(!listDet.SetItemText(itemIdx, 0, str))
		return false;

	str = wd.GetMethodName(elemIn->methodType);
	if(!listDet.SetItemText(itemIdx, 1, str))
		return false;

	str = elemIn->data;
	if(!listDet.SetItemText(itemIdx, 2, str))
		return false;

	return true;
}

bool DlgScanCfg::AddListElement(WorkCfgElement* elemIn)
{
	LV_ITEM lvi;
	int itemIdx;
	int res;
	CString str;

	if(elemIn==NULL) return true;

	itemIdx = listDet.GetItemCount();

	str = wd.GetPhaseName(elemIn->phaseType);
	lvi.mask     = LVIF_TEXT;
	lvi.iItem    = itemIdx;
	lvi.iSubItem = 0;
	lvi.pszText  = CT2A(str);
	res = listDet.InsertItem(&lvi);
	if(res==-1) return false;

	return SetItemProperties(itemIdx, elemIn);
}

//---------------------------------------------------------------------------

void DlgScanCfg::Initialize(void)
{
	vDesc.Empty();
	vComm.Empty();
	vAS.Empty();
	vMssg = _T("10");
	vMssd = _T("2");
	vMssi = _T("1");
	vMwt  = _T("3000");
	vMdt  = _T("0");

	vScanOrder = 0;
	vMimic     = 0;
	vArpCache  = 0;

	vShowArpDisc = FALSE;
	vScanAll     = FALSE;

	listDet.DeleteAllItems();
}

void DlgScanCfg::WorkCfgToData(void)
{
	vDesc = wc.xDescription;
	vComm = wc.xComment;
	vAS   = wc.xAddresses;
	vMssg.Format(_T("%d"), wc.xMaxSimScan);
	vMssd.Format(_T("%d"), wc.xMaxSimScanDns);
	vMssi.Format(_T("%d"), wc.xMaxSimScanIcmp);
	vMwt.Format (_T("%d"), wc.xMaxWaitTime);
	vMdt.Format (_T("%d"), wc.xMinDelay/1000);

	vShowArpDisc = wc.xShowArpDiscoveredHosts ? TRUE : FALSE;
	vScanAll     = wc.xScanAll ? TRUE : FALSE;

	switch(wc.xScanOrder){
		case __soNumeric :
			vScanOrder = 1;
			break;
		case __soRandomized :
			vScanOrder = 2;
			break;
		default:
			vScanOrder = 0;
			break;
	}

	vMimic = (int)wc.xMimicOS;

	vArpCache = (int)wc.xArpCacheOp;

	BuildPosValues();
	RefreshList();
}

void DlgScanCfg::WorkCfgFromData(void)
{
	wc.xDescription = vDesc;
	wc.xComment = vComm;
	wc.xAddresses = vAS;

	wc.xMaxSimScan = _tstoi(vMssg);
	wc.xMaxSimScanDns = _tstoi(vMssd);
	wc.xMaxSimScanIcmp = _tstoi(vMssi);
	wc.xMaxWaitTime = _tstoi(vMwt);
	wc.xMinDelay = 1000 * _tstoi(vMdt);

	wc.xShowArpDiscoveredHosts = vShowArpDisc ? true : false;
	wc.xScanAll = vScanAll ? true : false;

	switch(vScanOrder){
		case 1 :
			wc.xScanOrder = __soNumeric;
			break;
		case 2 :
			wc.xScanOrder = __soRandomized;
			break;
		default:
			wc.xScanOrder = __soAsEntered;
			break;
	}

	wc.xMimicOS = (MimicOS)vMimic;
	if((int)wc.xMimicOS<0 || (int)wc.xMimicOS>=MAX_COUNT_MIMIC)
		wc.xMimicOS = __mosRandom;

	wc.xArpCacheOp = (ArpCacheOp)vArpCache;
	if((int)wc.xArpCacheOp<0 || (int)wc.xArpCacheOp>=MAX_COUNT_ARPCOP)
		wc.xArpCacheOp = __acoIgnore;

	// list elements are pointers so their values are allready where they should be !
}

//---------------------------------------------------------------------------

BOOL DlgScanCfg::OnInitDialog()
{
	CRgnDialog::OnInitDialog();

	LVCOLUMN col;
	int i;

	SetProperties(skinIn, false, _T("Configuration"));

	cmbScanOrder.AddString(wd.GetScanOrderName(__soAsEntered));
	cmbScanOrder.AddString(wd.GetScanOrderName(__soNumeric));
	cmbScanOrder.AddString(wd.GetScanOrderName(__soRandomized));

	for(i=0; i<MAX_COUNT_MIMIC; i++)
		cmbMimic.AddString(wd.GetMimicName((MimicOS)i));

	cmbArpCache.AddString(wd.GetArpCacheOpName(__acoIgnore));
	cmbArpCache.AddString(wd.GetArpCacheOpName(__acoUse));
	cmbArpCache.AddString(wd.GetArpCacheOpName(__acoUpdate));
	cmbArpCache.AddString(wd.GetArpCacheOpName(__acoUpdOnly));

	listDet.SendMessage(LVM_SETVIEW, LV_VIEW_DETAILS, 0);

	listDet.SetExtendedStyle(LVS_EX_FULLROWSELECT);

	col.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH;
	col.fmt = LVCFMT_LEFT;
	col.cx = 120;
	col.pszText = "Phase";
	listDet.InsertColumn(0, &col);

	col.pszText = "Method";
	listDet.InsertColumn(1, &col);

	col.pszText = "Data";
	listDet.InsertColumn(2, &col);

	CWinApp *theApp;
	theApp = AfxGetApp();

	if(iconUp==NULL){
		if(theApp!=NULL)
			iconUp = theApp->LoadIcon(IDI_ICO_UP);
	}
	btnUp.SetIcon(iconUp);

	if(iconDown==NULL){
		if(theApp!=NULL)
			iconDown = theApp->LoadIcon(IDI_ICO_DOWN);
	}
	btnDown.SetIcon(iconDown);

	if(skinIn!=NULL){
		staDesc.textColor = skinIn->textColor;
		staComm.textColor = skinIn->textColor;
		staAS.textColor   = skinIn->textColor;
		staMSSG.textColor = skinIn->textColor;
		staMSSD.textColor = skinIn->textColor;
		staMSSI.textColor = skinIn->textColor;
		staMWT.textColor  = skinIn->textColor;
		staMDT.textColor  = skinIn->textColor;

		chkShowArpDisc.textColor = skinIn->textColor;
		chkScanAll.textColor     = skinIn->textColor;
	}

	WorkCfgToData();
	UpdateData(FALSE);

	// TODO:  Add extra initialization here

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

//---------------------------------------------------------------------------

void DlgScanCfg::OnBnClickedBtnOk()
{
	UpdateData(TRUE);
	WorkCfgFromData();

	retVal = true;
	EndDialog(IDOK);
}

void DlgScanCfg::OnBnClickedBtnCancel()
{
	retVal = false;
	EndDialog(IDABORT);
}

//---------------------------------------------------------------------------

void DlgScanCfg::OnBnClickedBtnAdd()
{
	WorkCfgElement *wce;

	dlgJob.skinIn = skinIn;
	dlgJob.wce.Initialize();
	dlgJob.SetHelpInfo(helpInfo, HELPID_DLG_SCANJOB);
	dlgJob.DoModal();
	if(dlgJob.retVal){
		wce = &dlgJob.wce;
		wce->pos = wc.GetJobCount() + 1;
		wc.AddJob(&dlgJob.wce);
		RefreshList();
	}
}

void DlgScanCfg::OnBnClickedBtnEdit()
{
	WorkCfgElement *wce;

	wce = GetSelectedElement();
	if(wce==NULL) return;

	dlgJob.skinIn = skinIn;
	dlgJob.wce.LoadFromPointer(wce);
	dlgJob.SetHelpInfo(helpInfo, HELPID_DLG_SCANJOB);
	dlgJob.DoModal();
	if(dlgJob.retVal){
		wce->LoadFromPointer(&dlgJob.wce);
		RefreshList();
	}
}

void DlgScanCfg::OnBnClickedBtnDel()
{
	WorkCfgElement *wce;

	wce = GetSelectedElement();
	if(wce==NULL) return;

	wc.DeleteJob(wce);
	RefreshList();
}

//---------------------------------------------------------------------------

void DlgScanCfg::OnOK()
{
	// CRgnDialog::OnOK();
}

void DlgScanCfg::OnCancel()
{
	// CRgnDialog::OnCancel();
}

//---------------------------------------------------------------------------

WorkCfgElement* DlgScanCfg::GetSelectedElement(void)
{
	WorkCfgElement *wce;
	int itemIdx;

	itemIdx = -1;
	itemIdx = listDet.GetNextItem(itemIdx, LVNI_SELECTED);
	if(itemIdx==-1) return NULL;

	wce = (WorkCfgElement *)listDet.GetItemData(itemIdx);

	return wce;
}

WorkCfgElement* DlgScanCfg::GetElementByPosValue(int posIn)
{
	WorkCfgElement* elem;
	int i, cnt;
	bool found;

	found = false;
	cnt = wc.GetJobCount();

	for(i=0; i<cnt && !found; i++){
		elem = wc.GetJobElement(i);
		if(elem!=NULL)
			if(elem->pos==posIn)
				found = true;
	}

	return found ? elem : NULL;
}

//---------------------------------------------------------------------------

void DlgScanCfg::OnBnClickedBtnAsh()
{
	ShowHelp();
}

//---------------------------------------------------------------------------

void DlgScanCfg::OnBnClickedBtnUp()
{
	WorkCfgElement* elemSel;
	WorkCfgElement* elemChg;
	int pos;

	elemSel = GetSelectedElement();
	if(elemSel==NULL) return;

	pos = elemSel->pos;
	elemChg = GetElementByPosValue(pos-1);
	if(elemChg==NULL) return;

	elemChg->pos++;
	elemSel->pos--;

	RefreshList();
}

void DlgScanCfg::OnBnClickedBtnDw()
{
	WorkCfgElement* elemSel;
	WorkCfgElement* elemChg;
	int pos;

	elemSel = GetSelectedElement();
	if(elemSel==NULL) return;

	pos = elemSel->pos;
	elemChg = GetElementByPosValue(pos+1);
	if(elemChg==NULL) return;

	elemChg->pos--;
	elemSel->pos++;

	RefreshList();
}

//---------------------------------------------------------------------------

void DlgScanCfg::OnNMDblclkListScandet(NMHDR *pNMHDR, LRESULT *pResult)
{
	WorkCfgElement *wce;

	LPNMITEMACTIVATE pNMIA = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	if(pNMIA!=NULL){
		wce = GetSelectedElement();
		if(wce!=NULL){
			dlgJob.skinIn = skinIn;
			dlgJob.wce.LoadFromPointer(wce);
			dlgJob.SetHelpInfo(helpInfo, HELPID_DLG_SCANJOB);
			dlgJob.DoModal();
			if(dlgJob.retVal){
				wce->LoadFromPointer(&dlgJob.wce);
				RefreshList();
			}
		}
	}

	*pResult = 0;
}

//---------------------------------------------------------------------------
